#ifndef __DEBUG__
// For printing purposes
#define __DEBUG__ 0
#endif

#include <iostream>
#include <cstdint>

#include "../VAR.hpp"
#include "../TERM.hpp"
#include "../EXPRESSION.hpp"
#include "../ADD.hpp"
#include "../SUB.hpp"

using namespace std;

// Global variables for printing and debugging purposes
int expr_depth = -1;
int bin_expr_depth = -1;

void test5() {
  if (__DEBUG__) cout << endl << "Beginning Test 5:" << endl;

  constexpr Variable<1> v;
  constexpr VariableTerm<1> t(v);
  if (__DEBUG__) cout << (ConstantTerm)(-2) << endl;  

  static_assert(v.place() == 1, "ERROR");
  
  // Needs g++-4.7.2 includes  
  constexpr std::tuple<int, int> test(0, 10);
  static_assert(v(test) == 10, "ERROR");

  int a=2, b=3;
  std::tuple<int, int> amin1(0, -a);
  std::tuple<int, int> amax1(0,  b);
  
  // Needs g++-4.7.2 includes
  constexpr std::tuple<int, int> amin2(0,  1);
  constexpr std::tuple<int, int> amax2(0, 10);
  // std::tuple<int, int> amin2(0,  1);
  // std::tuple<int, int> amax2(0, 10);

  // int min = (-2*t).Min(-a,b);
  // Not static, period
  int min = (-2*t).Min(amin1, amax1);
  if (__DEBUG__) cout << "\texpr: " << (-2*t) << endl;
  if (__DEBUG__) cout << "\tMin: " << min << endl;

  // constexpr int min2 = (-2*t).Min(1,10);
  // Not static, cannot make this constexpr and static_assert it
  // until N3305 become standard, workaround is to use ConstExprGet
  constexpr int min2 = (-2*t).Min(amin2, amax2);
  if (__DEBUG__) cout << "\tMin2: " << min2 << endl;

  // constexpr int min3 = (-2*(-5)*8*t).Min(1,10);
  // Not static, cannot make this constexpr and static_assert it
  // until N3305 become standard, workaround is to use ConstExprGet
  constexpr int min3 = (-2*(-5)*8*t).Min(amin2, amax2);
  if (__DEBUG__) cout << "\tMin3: " << min3 << endl;

  // constexpr int min4 = (-2*(-5+7)*8*t).Min(1,10);
  // Not static, cannot make this constexpr and static_assert it
  // until N3305 become standard, workaround is to use ConstExprGet
  constexpr int min4 = (-2*(-5+7)*8*t).Min(amin2, amax2);
  if (__DEBUG__) cout << "\tMin4: " << min4 << endl;

  static_assert(t.cst() > 0, "ERROR");
  // Not static, cannot make this constexpr and static_assert it
  // until N3305 become standard, workaround is to use ConstExprGet
  // static_assert(min == xxx, "ERROR");
  static_assert(min2 ==  -20, "ERROR");
  static_assert(min3 ==   80, "ERROR");
  static_assert(min4 == -320, "ERROR");

}

int main (void) {
  test5();
}
